<?php
/**
 * Created by PhpStorm.
 * User: kongqi
 * Date: 2019/12/2
 * Time: 21:29
 */

namespace App\Plugin\HostServer\Services;

use App\Plugin\HostServer\Models\PnHostSvDomain;
use GuzzleHttp\Client;

class DomainService
{
    public $apiUrl = '';//API地址
    public $key = '';//Api密钥
    public $searchArr = [];//搜索域名组合
    public $domainExt;//域名后缀
    public $domain;//域名不带任何后缀
    public $error = [];
    public $domainArr = [];//要去搜索的域名组合
    public $domainSystemArr = [];//系统表的里面数据
    public $domainSystemPriceArr = [];//系统表的里面数据

    public function __construct()
    {
        $this->apiUrl = config_cache_default('host_server.domain_api', 'https://api.dynadot.com/api3.xml');
        $this->key = config_cache_default('host_server.domain_key','C8a6w8w709Xo6tUH9J6p8h8q8OD7CE9G8AY9UQE');

        $this->domainSystemArr = PnHostSvDomain::domain();
        $search_support = [];
        foreach ($this->domainSystemArr as $k => $v) {
            $search_support[] = $v['name'];
            $this->domainSystemPriceArr[$v['name']] = [
                'register_money' => $v['register_money'],
                'renewal_money' => $v['renewal_money'],
                'migrate_money' => $v['renewal_money'],
                'origin_money' => $v['origin_money'],
            ];
        }
        //进行分组
        $this->searchArr = $search_support;

    }

    public function explodDomain($domain)
    {
        $domain_arr = explode('.', $domain);

        if (empty($domain_arr)) {
            $this->domain = $domain;
            $this->domainExt = '.com';
        } else {
            if (isset($domain_arr[1])) {
                $this->domainExt = '.' . $domain_arr[1];
            } else {
                $this->domainExt = '.com';
            }

            $this->domain = $domain_arr[0] ?? '';
        }
    }

    public function formatResult($msg, $code, $data = [])
    {
        $message = [
            'msg' => $msg,
            'code' => $code,
            'data' => $data
        ];
        return $message;
    }

    /**
     * 加入错误数组
     * @param array $error
     */
    public function addError($msg, $code, $data = [])
    {
        $error = $this->formatResult($msg, $code, $data);
        $this->error = array_merge($this->error, $error);
        return $this->error;
    }

    /**
     * 获取域名参数信息
     * @param int $page
     * @param array $ext
     * @param int $system 是否获取系统表里面数据
     */
    public function rangeDomain($page = 1, $ext = [], $system = 0)
    {

        if ($system) {

            $this->domainArr[$this->domainExt] = $this->domainSystemPriceArr[$this->domainExt] ?? 0;;
        } else {
            $this->domainArr['domain0'] = $this->domain . $this->domainExt;
        }
        if (empty($ext)) {
            $arr = array_slice($this->searchArr, ($page - 1) * 10, 10);
        } else {
            $arr = array_slice($ext, ($page - 1) * 10, 10);
        }

        foreach ($arr as $k => $v) {

            //存在了就过滤
            if ($v == $this->domainExt) {
                continue;
            }

            if ($system) {
                $this->domainArr[$v] = $this->domainSystemPriceArr[$v] ?? [];
            } else {
                $this->domainArr['domain' . ($k + 1)] = $this->domain . $v;
            }
        }

    }

    public function checkFormatRespone($data, $key, $only = 0)
    {
        $key = ucfirst($key);
        if (!isset($data[$key . 'Response'])) {
            $this->addError('格式不对', 99);
        }
        if ($only) {
            if (!isset($data[$key . 'Response'][$key . 'Header'])) {
                $this->addError('当前查询人数过多，请稍后再试', 9);
            }
        } else {
            if (!isset($data[$key . 'Response'][0][$key . 'Header'])) {
                $this->addError('当前查询人数过多，请稍后再试', 9);
            }
        }

    }

    /**
     * 这里不检查是否已经注册，用于快速续费和注册，前面需要过滤是否注册
     * 传递域名取得系统的价格，如果不想走接口，可以调用这个接口
     * @param $domain
     * @param int $page
     * @param array $ext
     * @param int $only
     */
    public function searchSystem($domain, $page = 1, $ext = [], $only = 0, $system = 0)
    {
        if (!$only) {
            //过滤掉www.开头
            $domain = preg_replace("#^www.#", "", $domain);
            $this->explodDomain($domain);

            if (empty($this->domain)) {
                return $this->addError('域名缺少', '1');
            }
        } else {
            if ($system) {
                $this->explodDomain($domain);

                if (empty($this->domain)) {
                    return $this->addError('域名缺少', '1');
                }
            }
        }

        //组合,分页

        if ($only) {
            //单个的时候

            if ($system) {
                $this->domainArr[$this->domainExt] = $this->domainSystemPriceArr[$this->domainExt] ?? [];
            } else {
                $this->domainArr['domain0'] = $domain;
            }
        } else {
            //判断是否指定了ext
            $this->rangeDomain($page, $ext, $system);
        }
        $r = [];
        if (empty($this->domainArr)) {
            return $this->addError('获取失败', '1');
        }
        if ($only) {

            foreach ($this->domainArr as $k => $v) {
                $r = [
                    'code' => 0,
                    'domain' => $this->domain . $k,
                    'has' => 0,
                    'http_status' => 1,
                    'price' => $this->salePrice((int)$v['register_money'], $k),
                    'error' => 0,
                    'market' => $this->marketPrice((int)$v['register_money'], $k),
                    'oprice' => (int)$v['register_money'] + 1000,
                    'renewal_price' => $this->salePrice((int)$v['register_money'], $k, 1),
                ];
            }
        } else {
            foreach ($this->domainArr as $k => $v) {
                $r[] = [
                    'code' => 0,
                    'domain' => $this->domain . $k,
                    'has' => 0,
                    'http_status' => 1,
                    'price' => $this->salePrice((int)$v['register_money'], $k),
                    'error' => 0,
                    'market' => $this->marketPrice((int)$v['register_money'], $k),
                    'oprice' => (int)$v['register_money'] + 1000,
                    'renewal_price' => $this->salePrice((int)$v['register_money'], $k, 1),
                ];
            }
        }

        return $this->formatResult('获取成功', 200, $r);

    }

    //请求接口价格
    public function search($domain, $page = 1, $ext = [], $only = 0)
    {
        if (!$only) {
            //过滤掉www.开头
            $domain = preg_replace("#^www.#", "", $domain);
            $this->explodDomain($domain);

            if (empty($this->domain)) {
                return $this->addError('域名缺少', '1');
            }
        }

        //组合,分页
        if ($only) {
            //单个的时候
            $this->domainArr['domain0'] = $domain;
        } else {
            //判断是否指定了ext
            $this->rangeDomain($page, $ext);
        }

        $command = 'search';
        $data = [
            'show_price' => 1,
            'language' => 'zh'
        ];

        $data = array_merge($this->domainArr, $data);
        $sp_data = $this->curl($data, $command);
        $sp_data = json_decode($sp_data, 1);
        $result = [];

        try {

            $this->checkFormatRespone($sp_data, $command, $only);
            if (!empty($this->error)) {
                return $this->error;
            }
            if ($only) {

                $v = $sp_data['SearchResponse'];
                $price = str_replace('in CNY', '', $v['SearchHeader']['Price'] ?? 0);
                $on_ext_arr = explode(".", $v['SearchHeader']['DomainName']);

                $result = [
                    'code' => $v['SearchHeader']['SuccessCode'],
                    'domain' => $v['SearchHeader']['DomainName'],
                    'has' => $v['SearchHeader']['SuccessCode'] == -1 ? 1 : $v['SearchHeader']['Available'] == 'no' ? 1 : 0,
                    'http_status' => $v['SearchHeader']['Status'],
                    'price' => $this->salePrice((int)$price, $on_ext_arr[1] ?? ''),
                    'error' => $v['SearchHeader']['Error'] ?? '',
                    'market' => $this->marketPrice((int)$price, $on_ext_arr[1] ?? ''),
                    'oprice' => (int)$price + 1000,
                    'renewal_price' => $this->salePrice((int)$price, $on_ext_arr[1] ?? '', 1),
                ];
            } else {
                foreach ($sp_data['SearchResponse'] as $k => $v) {
                    $on_ext_arr = explode(".", $v['SearchHeader']['DomainName']);
                    $price = str_replace('in CNY', '', $v['SearchHeader']['Price'] ?? 0);
                    $result[] = [
                        'code' => $v['SearchHeader']['SuccessCode'],
                        'domain' => $v['SearchHeader']['DomainName'],
                        'has' => $v['SearchHeader']['SuccessCode'] == -1 ? 1 : $v['SearchHeader']['Available'] == 'no' ? 1 : 0,
                        'http_status' => $v['SearchHeader']['Status'],
                        'price' => $this->salePrice((int)$price, $on_ext_arr[1] ?? ''),
                        'error' => $v['SearchHeader']['Error'] ?? '',
                        'market' => $this->marketPrice((int)$price, $on_ext_arr[1] ?? ''),
                        'oprice' => (int)$price + 1000,
                        'renewal_price' => $this->salePrice((int)$price, $on_ext_arr[1] ?? '', 1),
                    ];
                }
            }

            return $this->formatResult('获取成功', 200, $result);

        } catch (\Exception $exception) {
            return $this->addError('没有更多了' . $exception->getMessage(), 100);
        }
        return $this->error;

    }

    //注册域名
    public function regist($domain, $year)
    {
        if (empty($domain)) {
            return $this->addError('缺少域名', 97);
        }
        $command = 'register';
        $data = [
            'domain' => $domain,
            'duration' => $year ?: 1,
        ];

        $sp_data = $this->curl($data, $command);

        $sp_data = json_decode($sp_data, 1);
        $result = [];
        if ($sp_data['RegisterHeader']['SuccessCode'] == 0) {
            $result = [
                'code' => 200,
                'msg' => '注册成功',
                'status' => $sp_data['RegisterHeader']['Status']
            ];
        } elseif ($sp_data['RegisterHeader']['SuccessCode'] == 3) {
            $result = [
                'code' => 90,
                'msg' => '账号资金不足',
                'status' => $sp_data['RegisterHeader']['Status']
            ];
        } elseif ($sp_data['RegisterHeader']['SuccessCode'] == 1) {
            //{"RegisterHeader":{"SuccessCode":"1","Status":"not_available"}}
            //array:1 [
            $result = [
                'code' => 1,
                'msg' => '已被注册了',
                'status' => $sp_data['RegisterHeader']['Status']
            ];
        } else {
            $result = [
                'code' => 1,
                'msg' => '注册失败',
                'status' => $sp_data['RegisterHeader']['Status'] ?? ''
            ];
        }

        return $result;

    }

    //续费
    public function renewal($domain, $year)
    {

        if (empty($domain)) {
            return $this->addError('缺少域名', 97);
        }
        $command = 'renew';
        $data = [
            'domain' => $domain,
            'duration' => $year ?: 1,
        ];

        $sp_data = $this->curl($data, $command);

        //$sp_data='{"RenewHeader":{"SuccessCode":"0","Status":"success"},"RenewContent":{"Expiration":"1701647999000"}}';
        $sp_data = json_decode($sp_data, 1);


        //续费失败
        //{"RenewHeader":{"SuccessCode":"2","Status":"insufficient_funds"}}
        //资金不住：array:1 [
        //  "RenewHeader" => array:2 [
        //    "SuccessCode" => "2"
        //    "Status" => "insufficient_funds"
        //  ]
        //]
        //成功{"RenewHeader":{"SuccessCode":"0","Status":"success"},"RenewContent":{"Expiration":"1701647999000"}}


        if ($sp_data['RenewHeader']['SuccessCode'] == 0) {
            $result = [
                'code' => 200,
                'msg' => '续费成功',
                'status' => $sp_data['RenewHeader']['Status']
            ];
        } elseif ($sp_data['RenewHeader']['SuccessCode'] == 2) {
            $result = [
                'code' => 90,
                'msg' => '账号资金不足',
                'status' => $sp_data['RenewHeader']['Status']
            ];
        }
       else {
            $result = [
                'code' => 1,
                'msg' => '续费失败',
                'status' => $sp_data['RenewHeader']['Status'] ?? ''
            ];
        }


        return $result;

    }

    //查看域名信息
    public function show($domain)
    {
        if (empty($domain)) {
            return $this->addError('缺少域名', 97);
        }
        $command = 'domain_info';
        $data = [
            'domain' => $domain,

        ];

        $sp_data = $this->curl($data, $command);

        $sp_data = json_decode($sp_data, 1);

        $result = [];

        return $result;

    }
    //解析IP
    public function ip($domain,$data){
        //设置
        //获取参数设置
        if(count($data['main_record_data'])<0)
        {
            return $this->addError('缺少主域名参数','1');
        }
        if(count($data['main_record_data'])>18)
        {
            return $this->addError('主域名最多19个','1');
        }
        $main_record_type=[];//类型
        $main_record_type_key=0;
        $main_record=[];//ip
        $main_recordx=[];

        foreach ($data['main_record_data'] as $k=>$v)
        {
            if(isset($v['type']) && $v['type'] && isset($v['ip']) && $v['ip'])
            {
                $main_record_type['main_record_type'.$main_record_type_key]=$v['type'];
                $main_record['main_record'.$main_record_type_key]=$v['ip'];

                //如果是mx，还需要个值
                if($v['type']=='mx'){
                    if(!isset($v['value']))
                    {
                        return $this->addError('主域名参数MX缺少值','1');
                    }
                    if(empty($v['value']))
                    {
                        return $this->addError('主域名参数MX缺少值','1');
                    }
                    $main_recordx['main_recordx'.$main_record_type_key]=$v['value'];
                }
                $main_record_type_key++;
            }

        }
        $subdomain=[];
        $subdomain_key=0;
        $sub_record_type=[];
        $sub_record=[];
        $sub_recordx=[];//MX转发值
        if(isset($data['subdomain']))
        {
            if(count($data['subdomain'])>48){
                return $this->addError('子机域名最多49个','1');
            }
            if(!empty($data['subdomain']))
            {
                foreach ($data['subdomain'] as $k=>$v)
                {
                    if(isset($v['name']) && $v['name'] && isset($v['ip']) && $v['ip']){

                        $subdomain['subdomain'.$subdomain_key]=$v['name'];
                        $sub_record_type['sub_record_type'.$subdomain_key]=$v['type'];
                        $sub_record['sub_record'.$subdomain_key]=$v['ip'];
                        if($v['type']=='mx'){
                            if(!isset($v['value']))
                            {
                                return $this->addError('子域名参数MX缺少值','1');
                            }
                            if(empty($v['value']))
                            {
                                return $this->addError('子域名参数MX缺少值','1');
                            }
                            $sub_recordx['sub_recordx'.$subdomain_key]=$v['value'];
                        }
                        $subdomain_key++;

                    }

                }
            }
        }
        $command='set_dns2';
        $curl_data = [
            'domain' => $domain,
            'ttl'=>$data['glue_dns_ttl']??600
        ];

        //合并参数

        $curl_data = array_merge($main_record_type, $curl_data);
        $curl_data = array_merge($main_record, $curl_data);
        if(!empty($main_recordx))
        {
            $curl_data = array_merge($main_recordx, $curl_data);
        }
        if(!empty($subdomain)){
            $curl_data = array_merge($subdomain, $curl_data);
        }
        if(!empty($sub_record_type)){
            $curl_data = array_merge($sub_record_type, $curl_data);
        }
        if(!empty($sub_recordx)){
            $curl_data = array_merge($sub_recordx, $curl_data);
        }
        if(!empty($sub_record))
        {
            $curl_data = array_merge($sub_record, $curl_data);
        }

        $sp_data = $this->curl($curl_data, $command);

        $sp_data = json_decode($sp_data, 1);



        try{
            if($sp_data['SetDnsHeader']['SuccessCode']==0)
            {
                return $this->formatResult('设置成功',200);
            }else{
                $error=$sp_data['SetDnsHeader']['Error']??'';
                $error=str_replace('could not find domain in your account','域名不在你的账号里面',$error);
                return $this->formatResult('设置失败'.$error,2);
            }

        }catch ( \Exception $exception)
        {
            return $this->formatResult('设置失败'.$exception->getMessage(),1);
        }

    }

    //设置dns服务
    public function dns($domain, $data)
    {
        if (empty($domain)) {
            return $this->addError('缺少域名', 97);
        }
        if (empty($data)) {

            return $this->addError('缺少参数', 1);

        }
        $dn = [];
        if(!isset($data['dns']))
        {
            return $this->addError('缺少参数', 1);
        }
        if(empty($data['dns']))
        {
            return $this->addError('缺少参数', 1);
        }
        $key=0;
        $dns=[];
        foreach ($data['dns'] as $k=>$v)
        {
            if($v)
            {
                $dns['ns'.$key]=$v;
                $key++;
            }

        }

        if(empty($dns))
        {
            return $this->addError('缺少参数', 1);
        }

        $command = 'set_ns';
        $curl_data = [
            'domain' => $domain,
        ];
        if(!empty($dns))
        {
            $curl_data = array_merge($dns, $curl_data);
        }

        $sp_data = $this->curl($curl_data, $command);
        //格式不正确
        //{"SetNsHeader":{"SuccessCode":"-1","Status":"error","Error":"The name server '123.8.8.6' is not in the correct format"}}


        $sp_data = json_decode($sp_data, 1);

        try {
            $code = $sp_data['SetNsHeader']['SuccessCode'];
            $status = $sp_data['SetNsHeader']['Error']??'';

            if ($code == 0) {

                return $this->formatResult('设置成功', '200');
            } else {
                $status=str_replace('invalid characters in name server','无效的',$status);
                return $this->formatResult('设置失败'.$status, '1');
            }
        } catch (\Exception $exception) {
            $this->addError('设置失败', 1);
            return $this->error;
        }
    }
    //转发
    public function stealthUrl($domain,$data){
        if (empty($domain)) {
            return $this->addError('缺少域名', 97);
        }
        if (empty($data)) {
            return $this->addError('缺少参数', 1);
        }

        if(!isset($data['forward_url']))
        {
            return $this->addError('缺少参数', 1);
        }
        if(empty($data['forward_type']))
        {
            return $this->addError('缺少参数', 1);
        }

        $command = 'set_forwarding';
        $curl_data = [
            'domain' => $domain,
            'forward_url'=>$data['forward_url'],
            'is_temp '=>$data['forward_type']
        ];


        $sp_data = $this->curl($curl_data, $command);
        //{"SetForwardingHeader":{"SuccessCode":"0","Status":"success"}}



        //格式不正确
        $sp_data = json_decode($sp_data, 1);


        try {
            $code = $sp_data['SetForwardingHeader']['SuccessCode'];
            $status = $sp_data['SetForwardingHeader']['Status'];
            if ($code == 0) {
                return $this->formatResult('设置成功', '200');
            } else {
                return $this->formatResult('设置失败'.$status, '1');
            }
        } catch (\Exception $exception) {
            $this->addError('设置失败', 1);
            return $this->error;
        }
    }

    //隐身转发
    public function setStealth($domain,$data){
        if (empty($domain)) {
            return $this->addError('缺少域名', 97);
        }
        if (empty($data)) {
            return $this->addError('缺少参数', 1);
        }

        if(!isset($data['stealth_url']))
        {
            return $this->addError('缺少参数', 1);
        }
        if(empty($data['stealth_title']))
        {
            return $this->addError('缺少参数', 1);
        }

        $command = 'set_stealth';
        $curl_data = [
            'domain' => $domain,
            'stealth_url'=>$data['stealth_url'],
            'stealth_title'=>urldecode($data['stealth_title'])
        ];


        $sp_data = $this->curl($curl_data, $command);

       //{"SetStealthHeader":{"SuccessCode":"0","Status":"success"}}

        //格式不正确
        $sp_data = json_decode($sp_data, 1);


        try {
            $code = $sp_data['SetStealthHeader']['SuccessCode'];
            $status = $sp_data['SetStealthHeader']['Status'];
            if ($code == 0) {
                return $this->formatResult('设置成功', '200');
            } else {
                return $this->formatResult('设置失败'.$status, '1');
            }
        } catch (\Exception $exception) {
            $this->addError('设置失败', 1);
            return $this->error;
        }
    }
    /**
     * 销售价和续费价格
     * @param $origin_price
     * @return float|int
     * @throws \Exception
     */
    public function salePrice($origin_price, $ext = '', $renewal = 0)
    {
        $ext = '.' . $ext;
        if ($origin_price <= 0) {
            return 0;
        }
        if ($renewal) {
            $system_price = $this->domainSystemPriceArr[$ext]['renewal_money'] ?? 0;
            //dump($system_price);
        } else {
            $system_price = $this->domainSystemPriceArr[$ext]['register_money'] ?? 0;
        }
        if ($renewal) {
            // 续费费率
            $ratio = config_cache_default('host_server.domain_renewal_rate', 10);
        } else {
            //销售费率
            $ratio = config_cache_default('host_server.domain_rate', 10);
        }
        if ($system_price <= 0) {

            $add_price = round(bcmul($ratio, $origin_price, 2) / 100, 2);
        } else {

            $add_price = round(bcmul($ratio, $system_price, 2) / 100, 2);
            $origin_price = $system_price;//价格为系统价格
        }

        return ceil($origin_price + $add_price);

    }

    /**
     * 市场价
     * @param $origin_price
     * @return float|int
     * @throws \Exception
     */
    public function marketPrice($origin_price, $ext = '', $renewal = 0)
    {
        $ext = '.' . $ext;
        if ($origin_price <= 0) {
            return 0;
        }
        if ($origin_price <= 0) {
            return 0;
        }
        if ($renewal) {
            $system_price = $this->domainSystemPriceArr[$ext]['renewal_money'] ?? 0;
        } else {
            $system_price = $this->domainSystemPriceArr[$ext]['register_money'] ?? 0;
        }
        if ($renewal) {
            // 续费费率
            $ratio = config_cache_default('host_server.domain_renewal_rate', 10);
        } else {
            $ratio = config_cache_default('host_server.domain_market_rate', 40);
        }

        if ($system_price <= 0) {

            $add_price = round(bcmul($ratio, $origin_price, 2) / 100, 2);
        } else {
            $add_price = round(bcmul($ratio, $system_price, 2) / 100, 2);
            $origin_price = $system_price;//价格为系统价格
        }

        return ceil($origin_price + $add_price);

    }

    /**
     * 请求
     * @param $data
     * @param string $method
     * @return \Psr\Http\Message\StreamInterface
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function curl($data, $command, $method = 'get')
    {
        $data['command'] = $command;
        $data['key']=$this->key;
        $client = new Client([
            'verify' => false,

        ]);
        $method = strtoupper($method);
        $response = $client->request($method, $this->apiUrl, ['query' => $data]);
        $xml=$response->getBody();
        libxml_disable_entity_loader(true);
        $values = (json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)));
        return $values;

    }
}